package tech.aistar.corejava.day04.util;

import java.util.Arrays;

/**
 * @author success
 * @version 1.0
 * @description:本类用来演示:自定义数组工具类
 * @date 2019/7/18 0018
 */
public class ArrayUtil {
    public static void main(String[] args) {
        int[] ttt = null;
        //int[] ts = new int[0];
       // System.out.println(ttt.length);


        int[] arr = {1,2,2,2,3,1,4};

        //int[] arrs = null;//对象的默认的值都是null
        //null调用成员的时候,会抛出运行时异常java.lang.NullPointerException - 空指针异常.

       // int[] temp = delByElement(arr,2);

       // int[] temp = delByIndex2(arr,2);

        //int[] temp = delRepeatElement03(arr);
//        for (int t:temp){
//            System.out.println(t);
//        }

        System.out.println(Arrays.toString(sort02(arr)));
    }

    /**
     *  根据元素进行删除
     * 从arr数组中去删除所有的element
     * @param arr 原数组
     * @param element 需要删除的元素
     * @return 不包含删除的元素的新的数组.
     */
    public static int[] delByElement(int[] arr,int element){
        //1. 先进行参数的有效性判断
        //数组是否为空[null],数组中是否存在元素.
        if(arr == null || arr.length == 0){
            //返回一个信号量出来
            return new int[]{-1};//心里认为这是一个无效的数组.
        }

        //思考:由于数组一旦确定了,就不能再去动态改变数组的长度
        //原则:我们是不可能对原数组进行直接的增删操作的.
        //新建一个数组 - 保存不包含element以外的其余的数据
        //定义数组必不可少的语法:1. 确定数组的元素类型  2. 数组的长度
        //int[] temp = new int[];

        //到原数组arr中去找出需要删除的元素的个数
        //原数组的长度 - 个数 = 新的数组的长度

        //定义一个计数器 - 用来保存删除的元素的个数
        int count = 0;

        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == element){
                count++;
            }
        }
        //进行判断 - 判断原数组arr中是否存在element
        if(count == 0){
            return arr;
        }

        //找到了 - 新数组的长度arr.length - count
        int[] temp = new int[arr.length - count];

        //定义一个新的数组的下标计数器
        int pos = 0;

        //遍历arr
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] != element) {
                //temp的下标的确定一定是连续的
                temp[pos++] =arr[i];
            }
        }
        return temp;
    }

    /**
     * 下标是唯一的.
     *
     * 根据下标进行删除
     * @param arr 原数组
     * @param index 需要删除的下标
     * @return 不包含下标index处的值的新的数组
     */
    public static int[] delByIndex(int[] arr,int index){
        //1. 先进行参数的有效性判断
        //数组是否为空[null],数组中是否存在元素.
        if(arr == null || arr.length == 0 || index < 0 || index > arr.length - 1){
            //返回一个信号量出来
            return new int[]{-1};//心里认为这是一个无效的数组.
        }

        //2. 确定新的数组的长度
        int[] temp = new int[arr.length - 1];

        //3.遍历原数组,判断当前的下标是否等于index
        //如果不等于index,那么就存放到新的数组中

        //3. 需要为新的数组定义一个下标计数器 - 保证新的数组的下标是一个连续的
        int pos = 0;

        for (int i = 0; i < arr.length; i++) {
            if(i!=index){
                temp[pos++] = arr[i];
            }
        }
        return temp;
    }

    /**
     * 下标是唯一的.
     *
     *  1 2 2 3 3 4 5 6
     *
     * 根据下标进行删除
     * @param arr 原数组
     * @param index 需要删除的下标
     * @return 不包含下标index处的值的新的数组
     */
    public static int[] delByIndex2(int[] arr,int index){
        //1. 先进行参数的有效性判断
        //数组是否为空[null],数组中是否存在元素.
        if(arr == null || arr.length == 0 || index < 0 || index > arr.length - 1){
            //返回一个信号量出来
            return new int[]{-1};//心里认为这是一个无效的数组.
        }

        //此处对原数组arr进行了直接的操作
        //2. 从index处开始遍历,后面的一个值覆盖前面的一个值
        for (int i = index; i < arr.length - 1; i++) {
            //后面的覆盖前面的
            arr[i] = arr[i+1];
        }

        //目的是为了去除最后一位.
        int[] temp = new int[arr.length-1];
        for (int i = 0; i < arr.length - 1; i++) {
            temp[i] = arr[i];
        }
        return temp;
    }

    /**
     * 数组排重方式一:
     * @param arr
     * @return
     */
   public static int[] delRepeatElement01(int[] arr){
       if(arr == null || arr.length == 0){
           //返回一个信号量出来
           return new int[]{-1};//心里认为这是一个无效的数组.
       }
       //思路:遍历arr,然后拿到一个数,依次拿这个数和它后面的所有的数进行比较
       //如果某个位置上面的值和这个数相同,那么就调用根据下标进行删除.
       //保证:每次循环走完,后面出现的相同的值都将会被删除.
       for (int i = 0;i<arr.length;i++){
           for (int j = i + 1; j < arr.length; j++) {
                if(arr[i] == arr[j]){
                    //将j位置的值删除...
                    /*
                       arr - > 1,2,3,2,3,1,4
                           -> temp -> 1,2,3,2,3,4
                           arr = temp;

                           arr -> 1,2,3,2,3,4


                     */
                    //1 2 2 2 3 4 5
                    //
                    arr = delByIndex(arr,j);//根据下标进行删除 - 并没有对arr进行直接的操作.
                    j--;
                }
           }
       }
       return arr;
   }

    /**
     * 数组排重的第二种方式
     * {1,2,2,2,3,1,4};
     * {T,T,F,F,T,F,T}
     *
     *
     * @param arr
     * @return
     */
   public static int[]  delRepeatElement02(int[] arr){
       if(arr == null || arr.length == 0){
           //返回一个信号量出来
           return new int[]{-1};//心里认为这是一个无效的数组.
       }
       //1. 定义一个长度和原来数组一样的boolean[]
       boolean[] flags = new boolean[arr.length];
       //2. 进行统一的赋值
       Arrays.fill(flags,true);

       //3. 遍历arr
       for (int i = 0; i < arr.length; i++) {
           //判断当前下标后面的值是否和当前的arr[i]相同
           for (int j = i + 1; j < arr.length; j++) {
                if(arr[i] == arr[j]){
                    //需要将flags数组在j位置的值设置成false
                    flags[j] = false;
                }
           }
       }
       //定义一个计数器,用来确定新的数组的长度
       int count = 0;
       for (int i = 0; i < flags.length; i++) {
           if(flags[i]){
               count++;
           }
       }
       int[] temp = new int[count];

       //定义一个下标计数器
       int pos = 0;

       //遍历arr
       for (int i = 0; i < arr.length; i++) {
           if(flags[i]) {
               temp[pos++] = arr[i];
           }
       }
       return temp;
   }

    /**
     * {1,2,2,2,3,1,4}; - arr
     * {1,0,0,0,0,0,0}; - temp
     *
     * //1. 先将arr对应的{1,2,2,2,3,1,4}的第一个元素1直接放入到temp数中  temp[0] = 1
     * //2. 立即到arr中将数字1全部删除 - 我们自己写的根据元素进行删除的方法 - 返回的是新的数组{2,2,2,3,4} - 地址重新赋值给arr
     *      arr - > {2,2,2,3,4}
     *
     * //3. 将arr[0] 赋值给temp[1] = 2;
     *
     * //4. 过程中注意:arr一直在不停地重新指向一个新的数组
     *      永远将arr指向的那个数组的第一个元素存放到temp中
     *
     *
     *  //5. 一直到arr指向的那个数组的长度为0的时候退出
     *
     *  //6. 处理一下多余的0
     *
     * @param arr
     * @return
     */
   public static int[] delRepeatElement03(int[] arr){
       if(arr == null || arr.length == 0){
           //返回一个信号量出来
           return new int[]{-1};//心里认为这是一个无效的数组.
       }
       //定义一个数组,长度和原来的数组的长度是一样的.
       int[] temp = new int[arr.length];

       //定义一个下标计数器
       int pos = 0;

       do{
           //永远将arr指向的数组中的第一个元素赋值给temp
           //{1,2,2,2,3,1,4}
           temp[pos++] = arr[0];//1 - temp[0] = 1  temp[1] = 2
           //立即到arr根据元素进行删除操作 - arr[0] - 返回的是一个新的数组 - 重新赋值给arr
           arr = delByElement(arr,arr[0]);//arr - > {2,2,2,3,4}
           //进行循环退出的条件 - 当arr指向的数组的长度是0的时候,那么循环将会结束
           if(arr.length == 0){
               break;//跳出循环..
           }
       }while(true);

       //需要对多余的0进行处理
       return Arrays.copyOf(temp,pos);
   }

    /**
     * 选择 冒泡 快排 希尔 归并 ....[出去面试前一周]
     * 关于数组的排序
     *
     * 选择排序思路
     * 3 1 2 4 5 8 6
     * 1 2 3 4 5 8 6
     *
     * @return
     */
   public static int[] sort01(int[] arr){
       if(arr == null || arr.length == 0){
           //返回一个信号量出来
           return new int[]{-1};//心里认为这是一个无效的数组.
       }

       for (int i = 0; i < arr.length; i++) {
           for (int j = i + 1; j < arr.length; j++) {
               //3 1 2 4 5 8 6
               if(arr[i] > arr[j]){//arr[0]=3
                    arr[i] = arr[i]^arr[j];
                    arr[j] = arr[i]^arr[j];
                    arr[i] = arr[i]^arr[j];
                    //arr[0] = 1  arr[1] = 3
               }
           }
       }
       return arr;
   }

    /**
     * 冒泡算法 - 俩俩进行比较
     * 3 1 2 4 5 8 6
     * 1 2 3 4 5 6 8
     * @param arr
     * @return
     */
   public static int[] sort02(int[] arr){
       if(arr == null || arr.length == 0){
           //返回一个信号量出来
           return new int[]{-1};//心里认为这是一个无效的数组.
       }

       for (int i = 0; i < arr.length; i++) {
           for (int j = 0; j < arr.length-1-i; j++) {
               if(arr[j]>arr[j+1]){
                   arr[j] = arr[j]^arr[j+1];
                   arr[j+1] = arr[j]^arr[j+1];
                   arr[j] = arr[j]^arr[j+1];
               }
           }
       }
       return arr;
   }
}
